Pengenalan kepada Qiskit
Dalam notebook ini kita akan terokai cara memprogram quantum gates dan quantum circuits dengan Qiskit dan juga cara melaksanakannya pada simulator dan komputer kuantum sebenar menggunakan corak Qiskit. Kemudian kita akan perkenalkan cara-cara berbeza untuk mengekod maklumat dan akan diakhiri dengan contoh bonus Quantum Teleportation.
Sebelum kamu mulakan
Ikuti arahan Pasang dan sediakan jika kamu belum berbuat demikian, termasuk langkah-langkah untuk Sediakan penggunaan IBM Quantum™ Platform.
Disyorkan agar kamu menggunakan persekitaran pembangunan Jupyter untuk berinteraksi dengan komputer kuantum. Pastikan kamu memasang sokongan visualisasi tambahan yang disyorkan ('qiskit[visualization]'). Kamu juga akan memerlukan pakej matplotlib untuk bahagian kedua contoh ini.
Untuk belajar tentang pengkomputeran kuantum secara umum, lawati kursus Asas maklumat kuantum dalam IBM Quantum Learning
Import
# Added by doQumentation — required packages for this notebook
!pip install -q matplotlib numpy qiskit qiskit-aer qiskit-ibm-runtime
# Import necessary modules for this notebook
import time
import qiskit
from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector
from qiskit.visualization import plot_bloch_multivector, plot_state_qsphere
from qiskit_aer import AerSimulator
from qiskit.quantum_info import SparsePauliOp
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit_ibm_runtime import EstimatorV2 as Estimator
from qiskit_ibm_runtime import SamplerV2 as Sampler
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit.visualization import plot_histogram
print(qiskit.__version__)
2.3.1
Untuk melaksanakan quantum circuits kamu pada perkakasan, kamu perlu menyediakan akaun kamu dahulu. Kamu boleh lakukan seperti berikut:
- Pergi ke IBM Quantum® Platform yang dinaik taraf.
- Pergi ke sudut kanan atas (seperti yang ditunjukkan dalam gambar di atas), cipta token API kamu, dan salinnya ke lokasi yang selamat.
- Dalam sel seterusnya, gantikan
deleteThisAndPasteYourAPIKeyHeredengan kunci API kamu. - Pergi ke sudut kiri bawah (seperti yang ditunjukkan dalam gambar di atas) dan cipta instance kamu. Pastikan kamu memilih pelan terbuka.
- Selepas instance dicipta, salin kod CRN yang berkaitan. Kamu mungkin perlu muat semula untuk melihat instance tersebut.
- Dalam sel di bawah, gantikan
deleteThisAndPasteYourCRNHeredengan kod CRN kamu.
Lihat panduan ini untuk maklumat lanjut tentang cara menyediakan akaun IBM Cloud® kamu.
⚠️ Nota: Layani kunci API kamu seperti kata laluan yang selamat. Lihat panduan Persediaan Cloud untuk maklumat lanjut tentang penggunaan kunci API kamu dalam persekitaran selamat dan tidak dipercayai.
#your_api_key = "deleteThisAndPasteYourAPIKeyHere"
#your_crn = "deleteThisAndPasteYourCRNHere"
QiskitRuntimeService.save_account(
channel="ibm_quantum_platform",
token=your_api_key,
instance=your_crn,
overwrite=True
)
1. Quantum Gates dan Quantum Circuits
Quantum circuits adalah model untuk pengkomputeran kuantum di mana pengiraan merupakan urutan quantum gates. Mari kita lihat beberapa quantum gates yang popular.
X Gate
X gate bersamaan dengan putaran mengelilingi paksi X pada sfera Bloch sebanyak radian. Ia memetakan kepada dan kepada . Ia adalah setara kuantum bagi gate NOT untuk komputer klasik dan kadang-kadang dipanggil bit-flip.
# Let's apply an X-gate on a |0> qubit
qc = QuantumCircuit(1)
qc.x(0)
qc.draw(output='mpl')
# Let's see Bloch sphere visualization
sv = Statevector(qc)
plot_bloch_multivector(sv)

H Gate
Hadamard gate mewakili putaran sebanyak mengelilingi paksi yang berada di tengah-tengah antara paksi dan paksi .
Ia memetakan keadaan asas kepada , yang bermaksud bahawa pengukuran akan mempunyai kebarangkalian yang sama untuk menjadi 1 atau 0, mewujudkan 'superposisi' keadaan. Keadaan ini juga ditulis sebagai .
# Let's apply an H-gate on a |0> qubit
qc = QuantumCircuit(1)
qc.x(0)
qc.h(0)
qc.draw(output='mpl')
# Let's see Bloch sphere visualization
sv = Statevector(qc)
plot_bloch_multivector(sv)

CX Gate (CNOT Gate)
Gate controlled NOT (atau CNOT atau CX) beroperasi pada dua Qubit. Ia melakukan operasi NOT (bersamaan dengan menggunakan X gate) pada Qubit kedua hanya apabila Qubit pertama adalah dan jika tidak membiarkannya tidak berubah. Nota: Qiskit menomborkan bit dalam rentetan dari kanan ke kiri.
# Let's apply a CX-gate on |11>
qc = QuantumCircuit(2)
qc.x(0)
qc.x(1)
qc.cx(0,1)
qc.draw(output='mpl')
sv=Statevector(qc)
plot_state_qsphere(sv)

Cipta keadaan Bell pertama
# Create a Bell state circuit
qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0,1)
# Draw the circuit
qc.draw("mpl")
# Plot the state using q-sphere visualization
sv = Statevector(qc)
plot_state_qsphere(sv)
# q-sphere is useful for visualizing states when Bloch sphere fails to

Cipta keadaan Bell kedua
# Create a circuit with the second Bell state
qc = QuantumCircuit(2)
qc.x(0)
qc.h(0)
qc.cx(0,1)
qc.draw("mpl")
Penjelasannya ialah:
# Get the statevector of the circuit
sv = Statevector(qc)
# Plot the state using qsphere visualization
plot_state_qsphere(sv)

Cipta keadaan GHZ 3-Qubit
# Create a circuit with 3-qubit GHZ state
qc= QuantumCircuit(3)
qc.h(0)
qc.cx(0,1)
qc.cx(0,2)
qc.draw("mpl")
# Get the statevector of the circuit
sv = Statevector(qc)
# Plot the state using qsphere visualization
plot_state_qsphere(sv)

Cipta keadaan logo Qiskit
# Create a circuit with the Qiskit logo state
qc = QuantumCircuit(4)
qc.h(0)
qc.cx(0,1)
qc.cx(0,2)
qc.cx(0,3)
qc.x(1)
# Draw the circuit
qc.draw("mpl")
# Get the statevector of the circuit
sv = Statevector(qc)
# Plot the state using qsphere visualization
plot_state_qsphere(sv)

2. Cipta dan jalankan program kuantum mudah
Empat langkah untuk menulis program kuantum menggunakan corak Qiskit ialah:
-
Petakan masalah ke format natif kuantum.
-
Optimumkan circuits dan operator.
-
Laksanakan menggunakan fungsi primitif kuantum.
-
Analisis keputusan.
2.1 Petakan masalah ke format asli kuantum
Dalam program kuantum, litar kuantum adalah format asli untuk mewakili arahan kuantum, dan operator mewakili observable yang hendak diukur. Apabila membuat litar, kamu biasanya akan mencipta objek QuantumCircuit baru, kemudian tambah arahan secara berurutan.
Sel kod berikut mencipta litar yang menghasilkan keadaan GHZ — iaitu keadaan di mana tiga Qubit terbelit sepenuhnya antara satu sama lain.
Qiskit SDK menggunakan penomboran bit LSb 0, di mana digit ke- mempunyai nilai atau . Untuk maklumat lanjut, lihat topik Bit-ordering in the Qiskit SDK.
# Create a GHZ state circuit
qc = QuantumCircuit(3)
qc.h(0)
qc.cx(0,1)
qc.cx(0,2)
# Draw the circuit
qc.draw("mpl")
Lihat QuantumCircuit dalam dokumentasi untuk semua operasi yang tersedia.
Semasa membuat litar kuantum, kamu juga perlu pertimbangkan jenis data yang nak dikembalikan selepas pelaksanaan. Qiskit menyediakan dua cara untuk memulangkan data: kamu boleh peroleh taburan kebarangkalian bagi set Qubit yang dipilih untuk diukur, atau kamu boleh peroleh nilai jangkaan bagi suatu observable. Sediakan beban kerja kamu untuk mengukur litar dalam salah satu daripada dua cara ini dengan primitif Qiskit (dijelaskan secara terperinci dalam Langkah 3).
Contoh ini mengukur nilai jangkaan menggunakan submodul qiskit.quantum_info, yang ditentukan dengan operator (objek matematik yang digunakan untuk mewakili tindakan atau proses yang mengubah keadaan kuantum). Sel kod berikut mencipta enam operator Pauli tiga-Qubit: ZZZ, ZZX, ZII, XXI, ZZI dan III.
# Set up six different observables.
observables_labels = ["ZZZ", "ZZX", "ZII", "XXI", "ZZI", "III"]
observables = [SparsePauliOp(label) for label in observables_labels]
print(observables)
[SparsePauliOp(['ZZZ'],
coeffs=[1.+0.j]), SparsePauliOp(['ZZX'],
coeffs=[1.+0.j]), SparsePauliOp(['ZII'],
coeffs=[1.+0.j]), SparsePauliOp(['XXI'],
coeffs=[1.+0.j]), SparsePauliOp(['ZZI'],
coeffs=[1.+0.j]), SparsePauliOp(['III'],
coeffs=[1.+0.j])]
Di sini, operator seperti ZZI adalah singkatan bagi hasil darab tensor , yang bermaksud mengukur Z pada Qubit 2 dan Z pada Qubit 1 bersama-sama, serta mendapatkan maklumat tentang korelasi antara Qubit 2 dan Qubit 1. Nilai jangkaan seperti ini biasanya juga ditulis sebagai .
Jika keadaan yang kita perhatikan adalah keadaan GHZ tiga-Qubit, maka pengukuran sepatutnya bernilai 1.
2.2 Optimumkan litar dan operator
Semasa melaksanakan litar pada peranti, adalah penting untuk mengoptimumkan set arahan yang terkandung dalam litar dan meminimumkan kedalaman keseluruhan (lebih kurang bilangan arahan) litar tersebut. Ini memastikan kamu mendapat keputusan terbaik dengan mengurangkan kesan ralat dan bunyi. Selain itu, arahan litar mesti mematuhi Instruction Set Architecture (ISA) peranti Backend dan mesti mengambil kira get asas serta kesambungan Qubit peranti tersebut.
Kod berikut membuat instantiasi peranti sebenar untuk menghantar kerja, dan mengubah litar serta observable agar sesuai dengan ISA Backend berkenaan. Jika kamu belum pernah menyimpan kelayakan akses sebelum ini, ikut arahan di sini untuk mengesahkan diri dengan token API kamu.
# Choose a real backend
service = QiskitRuntimeService(channel='ibm_quantum_platform',)
backend = service.least_busy(min_num_qubits=156)
# print backend details
print(
f"Name: {backend.name}\n"
f"Version: {backend.backend_version}\n"
f"No. of qubits: {backend.num_qubits}\n"
f"Processor type: {backend.processor_type}\n"
)
Name: ibm_marrakesh
Version: 1.0.21
No. of qubits: 156
Processor type: {'family': 'Heron', 'revision': '2'}
# option to use the AerSimulator instead of a real quantum device
seed_sim=42
backend=AerSimulator.from_backend(backend,seed_simulator=seed_sim)
Transpile litar ke dalam litar ISA
# Convert to an ISA circuit and layout-mapped observables.
pm = generate_preset_pass_manager(backend=backend, optimization_level=2)
isa_circuit = pm.run(qc)
isa_circuit.draw("mpl", idle_wires=False)

mapped_observables = [
observable.apply_layout(isa_circuit.layout) for observable in observables
]
print(mapped_observables)
[SparsePauliOp(['IIIIIIIIIIIIIIIIZIIIIIZIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII'],
coeffs=[1.+0.j]), SparsePauliOp(['IIIIIIIIIIIIIIIIZIIIIIXIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII'],
coeffs=[1.+0.j]), SparsePauliOp(['IIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII'],
coeffs=[1.+0.j]), SparsePauliOp(['IIIIIIIIIIIIIIIIXIIIIIIIIIIIIIIIIIIXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII'],
coeffs=[1.+0.j]), SparsePauliOp(['IIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII'],
coeffs=[1.+0.j]), SparsePauliOp(['IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII'],
coeffs=[1.+0.j])]
2.3 Laksanakan menggunakan primitif kuantum
Komputer kuantum boleh menghasilkan keputusan rawak, jadi kamu biasanya mengumpul sampel output dengan menjalankan litar berkali-kali. Kamu boleh menganggarkan nilai observable menggunakan kelas Estimator. Estimator adalah salah satu daripada dua primitif; yang satu lagi adalah Sampler, yang boleh digunakan untuk mendapatkan data daripada komputer kuantum. Objek-objek ini mempunyai kaedah run() yang melaksanakan pilihan litar, observable, dan parameter (jika berkenaan), menggunakan primitive unified bloc (PUB).
Semasa menjalankan kod ini pada perkakasan kuantum sebenar, pertimbangkan untuk menggunakan teknik mitigasi dan penindasan ralat bagi mengurangkan hingar intrinsik komputer kuantum.
# Construct the Estimator instance.
estimator = Estimator(mode=backend)
estimator.options.resilience_level = 1
estimator.options.default_shots = 5000
Hantar kerja menggunakan primitif Estimator.
# One pub, with one circuit to run against six different observables.
job = estimator.run([(isa_circuit, mapped_observables)])
# Use the job ID to retrieve your job data later
print(f">>> Job ID: {job.job_id()}")
>>> Job ID: 97ecd036-1767-49b0-a1dc-c71638c3c3c4
/Users/jma/miniconda3/envs/3122/lib/python3.12/site-packages/qiskit_ibm_runtime/fake_provider/local_service.py:187: UserWarning: The resilience_level option has no effect in local testing mode.
warnings.warn("The resilience_level option has no effect in local testing mode.")
Selepas kerja dihantar, kamu boleh tunggu sehingga kerja selesai dalam contoh Python semasa, atau gunakan job_id untuk mendapatkan semula data pada masa lain. (Lihat bahagian tentang mendapatkan semula kerja untuk maklumat lanjut.)
Selepas kerja selesai, periksa outputnya melalui atribut result() kerja tersebut.
# This is the result of the entire submission. You submitted one Pub,
# so this contains one inner result (and some metadata of its own).
job_result = job.result()
# This is the result from our single pub, which had six observables,
# so contains information on all six.
pub_result = job.result()[0]
Sekarang kita juga boleh laksanakan litar menggunakan primitif Sampler
# We include the measurements in the circuit
qc.measure_all()
sampler = Sampler(mode=backend)
qc.draw(output="mpl")

Hantar kerja menggunakan primitif Sampler.
job_sampler = sampler.run(pm.run([qc]))
# Use the job ID to retrieve your job data later
print(f">>> Job ID: {job_sampler.job_id()}")
# Get the results
results_sampler = job_sampler.result()
>>> Job ID: a6ee4d2f-c80d-4a86-9a76-e4b1a74502e7
2.4 Analisis keputusan
Langkah analisis biasanya adalah di mana kamu mungkin memproses semula keputusan menggunakan, contohnya, mitigasi ralat pengukuran atau zero noise extrapolation (ZNE). Kamu mungkin akan suapkan keputusan ini ke dalam aliran kerja lain untuk analisis lanjut atau sediakan plot nilai dan data utama. Secara umumnya, langkah ini adalah khusus mengikut masalah kamu. Untuk contoh ini, plot setiap nilai jangkaan yang diukur untuk litar kita.
Nilai jangkaan dan sisihan piawai bagi observable yang kamu tentukan kepada Estimator boleh diakses melalui atribut PubResult.data.evs dan PubResult.data.stds hasil kerja. Untuk mendapatkan keputusan daripada Sampler, gunakan fungsi PubResult.data.meas.get_counts(), yang akan memulangkan dict pengukuran dalam bentuk bitstring sebagai kunci dan kiraan sebagai nilai yang sepadan. Untuk maklumat lanjut, lihat Get started with Sampler.
# Plot the result
from matplotlib import pyplot as plt
values = pub_result.data.evs
errors = pub_result.data.stds
# plotting graph
# Plotting with error bars
plt.errorbar(observables_labels, values, yerr=errors, fmt='-o', capsize=5)
plt.xlabel("Observables")
plt.ylabel("Values")
plt.title("Plot of Observables vs Values with Error Bars")
plt.grid(True)
plt.tight_layout()
plt.show()

Kita dapati bahawa observable dan mempunyai nilai jangkaan 1, kerana memperkenalkan dua tanda negatif yang saling menghapuskan, dan bertindak sebagai identiti, meninggalkan keadaan GHZ tidak berubah. Selebihnya observable mempunyai nilai jangkaan 0, kerana operator mereka memperkenalkan bilangan ganjil tanda negatif, atau operator membalikkan sejumlah Qubit yang menjadikan keadaan bertindih ortogonal.
Sekarang kita plot keputusan untuk Sampler
counts_list = results_sampler[0].data.meas.get_counts()
print(counts_list)
print(f"Outcomes : {counts_list}")
display(plot_histogram(counts_list, title="GHZ state"))
{'111': 480, '000': 503, '101': 8, '100': 9, '001': 3, '011': 6, '010': 10, '110': 5}
Outcomes : {'111': 480, '000': 503, '101': 8, '100': 9, '001': 3, '011': 6, '010': 10, '110': 5}

2.5 Skala kepada bilangan Qubit yang besar
Dalam pengkomputeran kuantum, kerja berskala utiliti adalah penting untuk membuat kemajuan dalam bidang ini. Kerja sedemikian memerlukan pengiraan dilakukan pada skala yang jauh lebih besar; bekerja dengan litar yang mungkin menggunakan lebih 100 Qubit dan lebih 1000 Gate. Contoh ini mengambil langkah kecil ke arah itu dengan menskalakan masalah GHZ kepada Qubit. Ia menggunakan aliran kerja corak Qiskit dan berakhir dengan mengukur nilai jangkaan .
Langkah 1. Petakan masalah
Tulis fungsi yang memulangkan QuantumCircuit yang menyediakan keadaan GHZ -Qubit (pada asasnya keadaan Bell yang diperluaskan), kemudian gunakan fungsi itu untuk menyediakan keadaan GHZ 10-Qubit dan kumpulkan observable yang hendak diukur.
def get_qc_for_n_qubit_GHZ_state(n: int) -> QuantumCircuit:
qc = QuantumCircuit(n)
qc.h(0)
for i in range(n-1):
qc.cx(i, i+1)
return qc
n = 10
qc_n_GHZ = get_qc_for_n_qubit_GHZ_state(n)
qc_n_GHZ.draw("mpl")

Seterusnya, petakan kepada operator yang diminati. Contoh ini menggunakan operator ZZ antara Qubit untuk meneliti kelakuan apabila mereka semakin jauh antara satu sama lain. Nilai jangkaan yang semakin tidak tepat (tercemar) antara Qubit yang jauh akan mendedahkan tahap hingar yang ada.
# ZZII...II, ZIZI...II, ... , ZIII...IZ
operator_strings = [
"Z" + i * "I" + "Z" + "I" * (n-i-2) for i in range(n-1)
]
print(operator_strings)
print(len(operator_strings))
operators = [SparsePauliOp(operator) for operator in operator_strings]
['ZZIIIIIIII', 'ZIZIIIIIII', 'ZIIZIIIIII', 'ZIIIZIIIII', 'ZIIIIZIIII', 'ZIIIIIZIII', 'ZIIIIIIZII', 'ZIIIIIIIZI', 'ZIIIIIIIIZ']
9
Langkah 2. Optimumkan masalah untuk pelaksanaan pada Backend kuantum
Ubah litar dan observable agar sesuai dengan ISA Backend.
# Convert to an ISA circuit and layout-mapped observables.
pm = generate_preset_pass_manager(backend=backend, optimization_level=2)
isa_circuit = pm.run(qc_n_GHZ)
isa_operators_list = [operator.apply_layout(isa_circuit.layout) for operator in operators]
Langkah 3. Laksanakan pada Backend
Hantar kerja dan jika kamu melaksanakannya pada perkakasan, aktifkan penindasan ralat menggunakan teknik untuk mengurangkan ralat yang dipanggil dynamical decoupling. Tahap ketahanan menentukan seberapa banyak ketahanan yang dibina terhadap ralat. Tahap yang lebih tinggi menghasilkan keputusan yang lebih tepat, dengan kos masa pemprosesan yang lebih lama. Untuk penjelasan lanjut tentang pilihan yang ditetapkan dalam kod berikut, lihat Configure error mitigation for Qiskit Runtime.
# Submit the circuit to Estimator
job = estimator.run([(isa_circuit, isa_operators_list)])
job_id = job.job_id()
/Users/jma/miniconda3/envs/3122/lib/python3.12/site-packages/qiskit_ibm_runtime/fake_provider/local_service.py:187: UserWarning: The resilience_level option has no effect in local testing mode.
warnings.warn("The resilience_level option has no effect in local testing mode.")
Langkah 4. Proses semula keputusan
Untuk lebih memahami kelakuan keadaan kuantum terbelit pada perkakasan sebenar, kita analisis korelasi berpasangan antara Qubit dalam asas Z. Secara khususnya, kita lihat nilai jangkaan ⟨Z₀Zᵢ⟩, yang mengukur sejauh mana Qubit 0 berkorelasi dengan setiap Qubit i yang lain. Khususnya kita akan plot:
Nilai apakah bagi yang kamu jangkakan dalam plot?
Pilihan:
a) Menurun apabila kita meningkatkan
b) Malar pada 1
c) Sisihan kecil sekitar 1
d) Berselang-seli antara 1 dan 0 bagi nilai ganjil dan genap
data = list(range(1, len(operators) + 1)) # Distance between the Z operators
result = job.result()[0]
values = result.data.evs # Expectation value at each Z operator.
values = [
v / values[0] for v in values
] # Normalize the expectation values to evaluate how they decay with distance.
plt.plot(data, values, marker="o", label=f"{n}-qubit GHZ state")
plt.xlabel("Distance between qubits $i$")
plt.ylabel(r"$\langle Z_i Z_0 \rangle / \langle Z_1 Z_0 \rangle $")
plt.legend()
plt.show()

Dalam plot ini kita perhatikan bahawa berfluktuasi sekitar nilai 1, walaupun dalam simulasi ideal semua sepatutnya bernilai 1.
Seperti yang kamu lihat, keputusan eksperimen 10 Qubit adalah baik tetapi masih ada beberapa ralat. Salah satu cara untuk memperbaiki keputusan adalah dengan melaksanakan keadaan GHZ dengan lebih cekap.
Biasanya seseorang melaksanakan keadaan GHZ dengan urutan get CNOT seperti tangga. Walau bagaimanapun, kamu boleh melaksanakan keadaan GHZ dengan lebih cekap, mengurangkan kedalaman 2-Qubit daripada n kepada n/2 atau kurang.
Satu metrik penting untuk menanda aras seberapa tepat keputusan akan menjadi, atau seberapa sedikit hingar yang akan ada bagi suatu litar, adalah kedalaman gate 2-Qubit. Ini kerana kadar ralat untuk gate 2-Qubit (~10 kali lebih tinggi daripada gate satu Qubit) mendominasi ralat keseluruhan litar. Gunakan kod berikut untuk mendapatkan kedalaman gate 2-Qubit bagi suatu litar.
qc.depth(lambda x: x.operation.num_qubits == 2)
def better_ghz(n):
"fan out"
s = int(n / 2)
qc = QuantumCircuit(n)
qc.h(s)
for m in range(s, 0, -1):
qc.cx(m, m - 1)
if not (n % 2 == 0 and m == s):
qc.cx(n - m - 1, n - m)
return qc
better_ghz(n).draw("mpl")

# Check 2-qubit gate depth before transpilation
qc_better_ghz = better_ghz(n)
qc_better_ghz.depth(lambda x: x.operation.num_qubits == 2)
5
Satu perkara menarik yang perlu diperhatikan di sini adalah bahawa kita berjaya mengurangkan kedalaman kuantum litar yang ingin dilaksanakan hanya dengan berfikir secara bijak dan memikirkan cara berbeza untuk mengaturcaranya. Walau bagaimanapun, akan ada situasi dan algoritma di mana kita tidak boleh bergantung pada helah bijak ini. Di sinilah Transpiler berguna — ia membantu kita mengoptimumkan semua aspek ini dengan cekap, jadi kita tak perlu terlalu risau tentangnya.
3. Mengekod Maklumat
3.1 Pengekodan amplitud
Sekarang setelah kita lihat cara membina litar kuantum, adalah menarik untuk meneroka bagaimana kita boleh mengekod maklumat klasik ke dalam keadaan kuantum. Satu kaedah yang berkuasa adalah pengekodan amplitud, di mana amplitud keadaan kuantum mewakili komponen vektor klasik.
Mari kita pertimbangkan contoh mudah. Katakan kita ingin mengekod vektor klasik
ke dalam keadaan kuantum dua Qubit. Matlamatnya adalah untuk menyediakan keadaan kuantum:
di mana (atau ) dan vektor dinormalkan supaya:
Sekarang kita pertimbangkan contoh khusus ini:
Maka keadaan kuantum yang sepadan ialah:
Keadaan ini boleh disediakan menggunakan gabungan Gate putaran dengan sudut dan untuk Qubit 0 dan 1 masing-masing
from qiskit import QuantumCircuit
from qiskit_aer import AerSimulator
import numpy as np
qc = QuantumCircuit(2)
qc.ry(np.pi / 6, 0)
qc.ry(np.pi / 4, 1)
simulator = AerSimulator()
qc.save_statevector()
result = simulator.run(qc).result()
statevector = result.get_statevector()
print("Statevector:", statevector)
qc.draw(output="mpl")
Statevector: Statevector([0.8923991 +0.j, 0.23911762+0.j, 0.36964381+0.j,
0.09904576+0.j],
dims=(2, 2))
from qiskit.quantum_info import Statevector
# Define our vector
v = np.array([0.8924, 0.3696, 0.2391, 0.0990])
v = v/np.linalg.norm(v)
# Create a statevector from the vector
state = Statevector(v)
# Initialize a quantum circuit with 2 qubits
qc = QuantumCircuit(2)
qc.initialize(state.data, [0, 1])
# Optional: simulate the state
print("Statevector:", state)
# Visualize the circuit
qc.decompose().decompose().decompose().decompose().decompose().draw("mpl")
Statevector: Statevector([0.89242154+0.j, 0.36960892+0.j, 0.23910577+0.j,
0.09900239+0.j],
dims=(2, 2))

Jadi kita dah tengok macam mana nak enkod maklumat menggunakan Gate putaran.
3.2 Enkod sudut dan Circuit berparameter
Satu cara yang menarik untuk mengenkod maklumat ke dalam komputer kuantum ialah dengan mereka bentuk Circuit kuantum yang mengandungi beberapa sudut putaran atau parameter yang boleh ditala untuk mewakili satu keluarga fungsi . Sebagai contoh, jom kita tengok Circuit kuantum berparameter berikut:
from qiskit import QuantumCircuit
from qiskit.circuit import Parameter
# Define a symbolic parameter
theta = Parameter("θ")
qc = QuantumCircuit(2)
# We applied a parametrized RX gate
qc.rx(theta, 0)
qc.cx(0, 1)
qc.draw("mpl")
Secara matematik, kita boleh analisa apakah keluarga fungsi yang boleh kita wakili dengan Circuit ini:
Jelas sekali bahawa bilangan keadaan yang boleh kita wakili dengan Circuit kuantum ini adalah terhad, kerana kita tak boleh wakili keadaan atau contohnya. Namun begitu, keluarga keadaan yang boleh kita wakili mula berkembang apabila kita tambah lebih banyak putaran di tempat yang sesuai:
from qiskit import QuantumCircuit
from qiskit.circuit import Parameter
# Define a symbolic parameter
theta1 = Parameter("θ1")
theta2 = Parameter("θ2")
qc = QuantumCircuit(2)
qc.rx(theta1, 0)
qc.rx(theta2, 1)
qc.cx(0, 1)
qc.draw("mpl")
Dalam kes ini, keadaan kuantum yang akan kita wakili ialah:
\begin{align*} \text{CNOT}_{01} \, R_x^{\{1}}(\theta_2) R_x^{\{0}}(\theta_1) \ket{00} &= \text{CNOT}_{01} \, R_x^{\{1}}(\theta_2)\left( \cos(\theta_1/2)\ket{00} - i\sin(\theta_1/2)\ket{10} \right) \\ &= \text{CNOT}_{01}\left( \cos(\theta_1/2)\cos(\theta_2/2)\ket{00} - i\cos(\theta_1/2)\sin(\theta_2/2)\ket{01} \right. \\ &\quad \left. - i\sin(\theta_1/2)\cos(\theta_2/2)\ket{10} + \sin(\theta_1/2)\sin(\theta_2/2)\ket{11} \right) \\ &= \cos(\theta_1/2)\cos(\theta_2/2)\ket{00} - i\cos(\theta_1/2)\sin(\theta_2/2)\ket{01} \\ &\quad + \sin(\theta_1/2)\sin(\theta_2/2)\ket{10} - i\sin(\theta_1/2)\cos(\theta_2/2)\ket{11} \end{align*}Kita dapat lihat bahawa Circuit ini menghasilkan keluarga keadaan kuantum yang lebih luas berbanding yang sebelumnya. Khususnya, ia kini boleh menghasilkan keadaan dengan amplitud tak sifar untuk atau yang tak mungkin dengan Circuit di atas. Walau bagaimanapun, Circuit ini masih bukan penjana keadaan kuantum sejagat, walaupun ia mungkin cukup ekspresif untuk mereka bentuk Circuit dengan fleksibiliti tertentu bagi mewakili fungsi-fungsi tertentu. Secara umumnya, semakin banyak parameter bebas (sudut) yang kita perkenalkan, semakin tinggi ekspresivitinya untuk menghampiri keadaan kuantum sembarangan.
Ansatz dan Circuit library
Jenis Circuit kuantum berparameter ini boleh digunakan untuk membina Ansatz, iaitu keadaan kuantum percubaan yang bertujuan untuk menghampiri penyelesaian sesuatu masalah. Ansatz-ansatz ini merupakan komponen utama Algoritma Kuantum Variasi, satu kelas algoritma kuantum-klasik hibrid yang menggunakan komputer kuantum untuk menilai fungsi kos dan pengoptimum klasik untuk meminimumkannya. Kita akan bincangkan topik-topik ini secara terperinci dalam Unit yang kemudian, tapi buat masa ini, kita akan perkenalkan cara membina Ansatz ringkas menggunakan Circuit library dalam Qiskit.
from qiskit.circuit.library import efficient_su2
SU2_ansatz = efficient_su2(4, su2_gates=["rx", "y"], entanglement="linear", reps=1)
SU2_ansatz.decompose().draw(output="mpl")

Kita dah tengok macam mana nak bina Ansatz ringkas menggunakan fungsi efficient_su2 daripada qiskit.circuit.library yang mampu menghasilkan pelbagai jenis keadaan kuantum dengan menala parameternya .
Kesimpulan
Dalam notebook ini, kamu dah belajar cara membina Circuit kuantum, mulai daripada membina Gate kuantum hinggalah mendefinisikan dan mengukur observable, serta cara melaksanakan Circuit ini dengan cekap pada simulator mahupun perkakasan kuantum sebenar. Kamu juga dah tengok kepentingan reka bentuk Circuit yang teliti untuk meminimumkan ralat ketika bekerja dengan peranti kuantum sebenar, serta strategi untuk menskalakan Circuit kepada bilangan Qubit yang lebih besar, terutamanya melalui contoh keadaan GHZ. Selain itu, kamu dah terokai pelbagai teknik untuk mengenkod maklumat klasik ke dalam keadaan kuantum, termasuk enkod amplitud dan enkod sudut. Dengan semua ini, kamu dah bersedia sepenuhnya untuk beralih ke sesi seterusnya dan mula bekerja dengan algoritma kuantum.
Memasang Qiskit Code Assistant dalam VSCode
Klik pautan ini dan ikuti arahan yang diberikan.
Bonus: Teleportasi Kuantum
Bila kamu dengar istilah teleportasi kuantum, mungkin kamu terbayang teknologi sci-fi futuristik yang menghancurkan sesuatu objek di satu tempat dan memunculkannya semula di tempat yang jauh. Tapi teleportasi kuantum langsung tak seperti itu. Sebenarnya, yang "diteleportkan" bukan jirim, tapi maklumat.
Teleportasi kuantum membolehkan pemindahan keadaan kuantum sebuah Qubit dari satu lokasi ke lokasi lain. Walaupun pemindahan ini nampak seolah-olah berlaku serta-merta, ia tidak melanggar hukum fizik. Macam mana boleh jadi begitu? Jom kita selami!
Teleportasi kuantum ialah satu protokol yang membolehkan pengirim (Alice) menghantar keadaan sebuah Qubit q kepada penerima (Bob) menggunakan dua sumber utama: sepasang Qubit berentang yang dikongsi bersama a dan b, serta dua bit komunikasi klasik c0 dan c1.
Pada dasarnya, protokol ini memerlukan:
q: Qubit Alice, pada mulanya dalam keadaan yang mahu diteleportkan.a: Separuh milik Alice daripada pasangan berentang yang dikongsi.b: Separuh milik Bob daripada pasangan berentang yang dikongsi.c0,c1: Bit klasik untuk menyimpan keputusan pengukuran Alice.
Dan macam mana ia berfungsi? Aliran kerjanya adalah seperti berikut:
- Sediakan keadaan Alice pada
q. Kita akan cipta satu keadaan khusus seperti untuk pengesahan. - Cipta keberangkutan: Jana pasangan Bell antara
adanb. - Operasi Alice: Alice melakukan "pengukuran Bell" pada dua Qubit miliknya (
qdana) dan menyimpan keputusan klasik dalamc0danc1. - Komunikasi klasik: Alice menghantar dua bit klasiknya (
c0,c1) kepada Bob. - Pembetulan Bob: Bob mengaplikasi Gate kuantum tertentu (X dan/atau Z) pada Qubit miliknya (
b), bergantung pada nilaic0danc1yang diterimanya.
Kalau semua langkah dilakukan dengan betul, Qubit Bob b akan berakhir dalam keadaan , iaitu keadaan asal Qubit Alice q!
Untuk penjelasan dan penerokaan yang lebih mendalam tentang teleportasi kuantum, termasuk penerangan matematik tentang kenapa protokol ini berfungsi, kamu boleh rujuk sumber IBM Quantum Learning: Teleportasi Kuantum. Ini merupakan sebahagian daripada kursus Asas Maklumat Kuantum.
import matplotlib.pyplot as plt
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister
from qiskit_aer import AerSimulator
from qiskit.visualization import plot_histogram, plot_bloch_multivector
# Define individual quantum registers for each qubit
q = QuantumRegister(1, name='q') # message qubit
a = QuantumRegister(1, name='a') # Alice's entangled qubit
b = QuantumRegister(1, name='b') # Bob's entangled qubit
# Classical register for Alice's measurements
cr_alice = ClassicalRegister(2, name='c_alice')
# Create quantum circuit
teleport_qc = QuantumCircuit(q, a, b, cr_alice, name='Teleportation')
# Step 1: Prepare message state |+⟩ on q
teleport_qc.h(q[0])
teleport_qc.barrier()
# Step 2: Create entanglement between a and b
teleport_qc.h(a[0])
teleport_qc.cx(a[0], b[0])
teleport_qc.barrier()
# Step 3: Alice's Bell measurement
teleport_qc.cx(q[0], a[0])
teleport_qc.h(q[0])
teleport_qc.barrier()
# Step 4: Alice measures q and a
teleport_qc.measure(q[0], cr_alice[0])
teleport_qc.measure(a[0], cr_alice[1])
teleport_qc.barrier()
# Step 5: Bob's conditional measurements
with teleport_qc.if_test((cr_alice[1], 1)):
teleport_qc.x(b[0])
with teleport_qc.if_test((cr_alice[0], 1)):
teleport_qc.z(b[0])
# Draw the circuit
teleport_qc.draw(output='mpl')

Selepas melaksanakan protokol, satu soalan penting timbul: macam mana kita nak sahkan bahawa teleportasi berjaya? Kita tak boleh "melihat" secara langsung keadaan Qubit Bob selepas protokol. Namun, memandangkan kita menyediakan keadaan awal Alice (kita pilih ), kita boleh menggunakan satu jenis simulasi khas untuk semak sama ada Qubit Bob b berakhir dalam keadaan yang sama.
Kita akan guna AerSimulator dengan save_statevector untuk semak sama ada Qubit Bob b berakhir dalam keadaan asal Alice (). Simulator ini mengira vektor keadaan kuantum akhir,
kemudian mewakilinya menggunakan plot_bloch_multivector untuk menggambarkan Qubit Bob (b) berbanding keadaan awal Alice (q).
# Simulate the teleportation circuit
sv_simulator = AerSimulator(method='statevector')
teleport_qc_sv = teleport_qc.copy()
teleport_qc_sv.save_statevector()
# Execute the circuit on the statevector simulator
job_sv = sv_simulator.run(teleport_qc_sv)
result_sv = job_sv.result()
# Get the final statevector
final_statevector = result_sv.get_statevector()
print("Visualizing final qubit states:")
display(plot_bloch_multivector(final_statevector))
print("Note that Alice's qubits have collapsed to |00⟩, |01⟩, |10⟩, or |11⟩, while Bob's qubit is in the original state |+⟩.")
Visualizing final qubit states:

Note that Alice's qubits have collapsed to |00⟩, |01⟩, |10⟩, or |11⟩, while Bob's qubit is in the original state |+⟩.
Seperti yang dapat kita lihat dari visualisasi, dua Qubit pertama (milik Alice) telah runtuh ke 0 atau 1. Sementara itu, Qubit ketiga (milik Bob), yang diwakili dalam sfera Bloch ketiga, menunjuk sepanjang paksi x, menandakan ia berada dalam keadaan , jadi kita telah berjaya melaksanakan protokol teleportasi kuantum!
Ringkasan
Pada ketika ini, adalah berguna untuk buat ringkasan ringkas tentang apa yang telah kita capai:
- Alice telah menghantar keadaan kuantum yang tidak diketahui kepada Bob.
- Tiada zarah fizikal yang dipindahkan.
- Keadaan asal pada Qubit Alice musnah, selaras dengan teorem Tanpa-Pengklonan.
Walau bagaimanapun, teleportasi kuantum masih memerlukan komunikasi klasik (keputusan pengukuran Alice yang dihantar kepada Bob), dan itulah yang menjelaskan mengapa proses ini tidak membenarkan pemindahan maklumat lebih laju daripada cahaya dan sepenuhnya konsisten dengan semua undang-undang fizik yang diketahui.